// 设置标题
export function setTitle(title) {
    document.title = title;
}

// 多对象合并
export function merge() {

}

// 是否存在某个对象
export function hasOwn(obj, key) {
    return Object.prototype.hasOwnProperty.call(obj, key);
}

// 判断类型
export function type(o) {
    return Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
}

// 是否函数
export function isFunction(o) {
    return type(o) === 'function';
}

// 是否数值
export function isNumber(o) {
    return type(o) === 'number';
}

// 实现一个深拷贝
export function copy(target) {

}

export function deepClone(target) {
    // function handleWhile(isArr, array, target ,res){
    //     let len = array.length;
    //     let index = -1;
    //     while(++index<len){
    //         // val,  key
    //         // callback(array[index], index);
    //         let key = index;
    //         // 对象的 key
    //         if(!isArr) key = array[index];
    //         res[key] = clone(target[key], map);
    //     }
    // }
    function clone(target, map) {
        // 引用类型：对象、数组
        // 特殊类型：Symbol
        // RegExp、Date、Function、Error 不需要遍历
        function handleOtherData(target) {
            let type = type(target);
            switch (type) {
                case 'date':
                    return new Date(target);
                    break;
                case 'regExp':
                    return cloneReg(target);
                    break;
                case 'function':
                    return cloneFunction(target);
                    break;
            }
        }

        // 克隆 Symbol
        function cloneSymbol(target){
            // 字符串化 Symbol
            let a = String(target);
            // 截取 Symbol(xxx) 里的参数值
            let b = a.slice(7, -1);
            return Symbol(b);
        }

        // 克隆 RegExp，正则的 source 属性为一个字符串，无论是不是 new 生成的
        function cloneReg(target){
            // let reFlags = /\w*$/;
            // // global、multiline、ignoreCase、source、lastIndex
            // let result = new target.constructor(target.source, reFlags.exec(target));
            // result.lastIndex = target.lastIndex;
            // 正则 可以直接这样复制
            return new RegExp(target);
        }

        // 通过 instanceof Error 来判断
        function cloneError(target){
            return new target.constructor(target);
        }

        // 克隆 Function，还得判断是不是箭头函数？
        function cloneFunction(target){
            let targetStr = target.toString();
            let paramsReg = /\([^\)*]\)/;
            if(target.prototype){
                //过滤出 params 和 body
                let params = targetStr.match(paramsReg)[0].trim().slice(1,-1).split(',');
                let firstIndex = targetStr.indexOf('{');
                let lastIndex = targetStr.lastIndexOf('}');
                let body = targetStr.slice(firstIndex+1,lastIndex-1);
                if(params.length){
                    return new Function(...params,body);
                }else{
                    return new Function(body);
                }
            }else{
                // 箭头函数没有作用域？
                return eval(targetStr);
            }
        }

        if (target != null && typeof target == 'object') {
            let isArr = Array.isArray(target);
            let res = isArr ? [] : {};
            // 此对象已经被处理过，直接返回
            if (map[target]) return map.get(target);
            map.set(target, res);

            // 换成 while 处理数组和对象的复制
            for (var k in target) {
                if (target.hasOwnProperty(k)) {
                    res[k] = clone(target[k], map);
                }
            }
            // let keys = isArr?undefined:Object.keys(target);
            // // 遍历数组、遍历对象
            // function callback(value,key){
            //     if(keys){
            //         key = value;
            //     }
            //     res[key] = clone(target[key], map);
            // }
            // // 通过循环处理数组或者 keys
            // handleWhile(isArr, isArr?target:keys, target, res);
            return res;
        } else {
            return target;
        }
    }
    // 通过 map
    // WeakMap 不需要手动释放内存
    let map = new WeakMap();

    let result = clone(target, map);
    map = null;
    return result;
}
